package model;

import utils.EnumType.UnitInfo;
import utils.EnumType.UnitTime;
import utils.Formatter;
import utils.HZ;

/**
 * Banda di un collegamento. La classe contiene alcune funzioni di utilità come quelle per formattare i dati
 * da utilizzare in Libvirt o in Traffic Control e quelle per calcolare i parametri del token bucket.
 * 
 * @author Dumella De Rosa Gennaro
 */
public class Bandwidth {
	
	private UnitInfo unit;
	private UnitTime period;
	private double value;
	
	public Bandwidth(UnitInfo unit, double value){
		this.unit = unit;
		this.value = value;
		this.period = UnitTime.second;
	}
	
	/**
	 * Restituisce il valore della banda formattata secondo la sintassi di Libvirt. Ecco alcuni esempi di
	 * come i valori vengono formattati: 2Mb/s, 256Kb/s, 0.23Gb/s.
	 * 
	 * @return {@link String}
	 */
	public String toLibvirtString(){
		return toLibvirtString(this.value);
	}
	
	/**
	 * Restituisce il valore della banda formattata secondo la sintassi di TC. Ecco alcuni esempi:
	 * 2mbps, 256kbps, 0.23gbps.
	 * 
	 * @return {@link String}
	 */
	public String toTrafficControlString(){
		 return toTrafficControlString(this.value);
	}
	
	/**
	 * Restituisce il comando per impostare il token bucket secondo la sintassi di TC. Solo il valore
	 * della banda deve essere impostato. Gli parametri parametri obligatori, <b>burst</b> e <b>latency</b>,
	 * che servono a definire il token bucket sono calcolati in maniera automatica utilizzando particolari
	 * funzioni private. Ecco alcune esempi di stringhe restituite:
	 * 		(1) tbf rate 2.266mbit burst .0028325mbit latency 100.0ms ;
	 * 		(2) tbf rate 2.266mbit burst .0028325mbit latency 100.0ms
	 * 
	 * @return s
	 */
	public String toTokenBucketString(){
		
		String s = "tbf rate " + toTrafficControlString(this.value) + 
					" burst " + toTrafficControlString(generateBurst()) + 
					" latency " + generateLatency()+"ms";
		 
		return s;
	}
	
	
	/**
	 * Metodo privato che restituisce il valore della banda, passata come parametro in ingresso, 
	 * formattata secondo la sintassi di Libvirt.
	 * 
	 * @param value - rate della banda 
	 * @return {@link String} che rappresenta la banda secondo la sintassi Libvirt.
	 */
	private String toLibvirtString(double value){
		 String s = Formatter.DecimalFormatter(value);
		 if(unit==UnitInfo.gigabit)
			 s += "Gb/s";
		 else if (unit==UnitInfo.megabit)
			 s += "Mb/s";
		 else 
			 s += "Kb/s";
		 
		 return s;
	}
	
	/**
	 * Metodo privato che restituisce il valore della banda, passata come parametro in ingresso, 
	 * formattata secondo la sintassi di Traffic Controll.
	 * 
	 * @param value - rate della banda 
	 * @return {@link String} che rappresenta la banda secondo la sintassi TC.
	 */
	private String toTrafficControlString(double value){
		 String s = Formatter.DecimalFormatter(value);
		 if(unit==UnitInfo.gigabit)
			 s += "gbit";
		 else if (unit==UnitInfo.megabit)
			 s += "mbit";
		 else
			 s += "kbit"; //valore di default
		 
		 return s;
	}
	
	/**
	 * Funzione privata che definisce il modo in cui e' calcolato il parametro burst. 
	 * In questo caso e' funzione del parametro rate e della variabile HZ.
	 * 
	 * @return il valore del parametro burst
	 */
	private double generateBurst(){
		return ((this.value/8)/HZ.getHZ())*10;
	}
	
	/**
	 * Funzione privata che definisce il modo in cui e' calcolato il parametro latency. 
	 * In questo caso e' funzione dei parametri rate e burst e della variabile HZ.
	 * 
	 * @return il valore del parametro latency
	 */
	private double generateLatency(){
		return (this.value/8)/(generateBurst());
	}
	
	/* Metodi GET */
	public String getUnit() {
		return unit.toString();
	}

	public double getValue() {
		return value;
	}
	
	public UnitTime getPeriod() {
		return period;
	}

	public static void main(String[] args) 
	{
		Bandwidth b = new Bandwidth(UnitInfo.megabit,2.26600);
		System.out.println(b.toLibvirtString());
		
		Bandwidth b1 = new Bandwidth(UnitInfo.gigabit,100000.20);
		System.out.println(b1.toTrafficControlString());
		Bandwidth b2 = new Bandwidth(null,0.001000);
		System.out.println(b2.toTrafficControlString());
		
		System.out.println(b.toTokenBucketString());
		System.out.println(b1.toTokenBucketString());

	}

}
